﻿using System.Security.Authentication;
using ApiLib.AppStart;
using ApiLib.Models;
using Furion;
using Furion.DataValidation;
using Furion.FriendlyException;
using Furion.UnifyResult;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;

namespace ApiLib.Common;

/// <summary>
/// 规范化返回结果
/// </summary>
[UnifyModel(typeof(BaseResponse<>))]
public class DefaultResultProvider : IUnifyResultProvider
{
    /// <summary>
    /// 数字类型
    /// </summary>
    private readonly List<Type> _numberTypes =
    [
        typeof(byte), typeof(char), typeof(short), typeof(int),
        typeof(double), typeof(float), typeof(long), typeof(decimal)
    ];

    private object? DefaultResultOnException(FilterContext context, object data)
    {
        if (context.ActionDescriptor is ControllerActionDescriptor descriptor)
        {
            var returnType = descriptor.MethodInfo.ReturnType;
            if (_numberTypes.Contains(returnType))
            {
                return 0;
            }

            if (returnType == typeof(bool))
            {
                return false;
            }

            if (returnType == typeof(string))
            {
                return "";
            }

            return null;
        }

        return data;
    }

    /// <summary>
    /// JWT 授权异常返回值
    /// </summary>
    /// <param name="context"></param>
    /// <param name="metadata"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public IActionResult OnAuthorizeException(DefaultHttpContext context, ExceptionMetadata metadata)
    {
        return BadPageResult.Status401Unauthorized;
    }

    /// <summary>
    /// 异常返回值
    /// </summary>
    /// <param name="context"></param>
    /// <param name="metadata"></param>
    /// <returns></returns>
    public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
    {
        if (context.Exception is MyAuthenticationFailureException or AuthenticationException)
        {
            return BadPageResult.Status401Unauthorized;
        }

        //UnauthorizedAccessException jwt
        if (context.Exception is MyUnauthorizedAccessException or UnauthorizedAccessException)
        {
            return BadPageResult.Status403Forbidden;
        }

        var data = DefaultResultOnException(context, metadata.Data);
        return new JsonResult(BaseResponse<object>.Failed(metadata.Errors.ToString() ?? "", data),
            UnifyContext.GetSerializerSettings(context));
    }

    /// <summary>
    /// 成功返回值
    /// </summary>
    /// <param name="context"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public IActionResult OnSucceeded(ActionExecutedContext context, object data)
    {
        return new JsonResult(BaseResponse<object>.Success(data), UnifyContext.GetSerializerSettings(context));
    }

    /// <summary>
    /// 验证失败返回值
    /// </summary>
    /// <param name="context"></param>
    /// <param name="metadata"></param>
    /// <returns></returns>
    public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)
    {
        var data = DefaultResultOnException(context, metadata.Data);
        if (metadata.ValidationResult is Dictionary<string,string[]> dict)
        {
            var enumerable = dict.Values.Select(strings => string.Join(",", strings));
            return new JsonResult(BaseResponse<object>.Failed(string.Join(",", enumerable), data),
                UnifyContext.GetSerializerSettings(context));
        }
        return new JsonResult(BaseResponse<object>.Failed(metadata.Message, data),
            UnifyContext.GetSerializerSettings(context));
    }

    /// <summary>
    /// 特定状态码返回值 return new BadPageResult(401);
    /// </summary>
    /// <param name="context"></param>
    /// <param name="statusCode"></param>
    /// <param name="unifyResultSettings"></param>
    /// <returns></returns>
    public async Task OnResponseStatusCodes(HttpContext context, int statusCode,
        UnifyResultSettingsOptions unifyResultSettings = null)
    {
        // 设置响应状态码
        UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);
        if (GlobalConfig.BaseResponse != null)
        {
            // BaseConfig.BaseResponse.Invoke(statusCode, context.Response);
            GlobalConfig.BaseResponse(statusCode, context.Response);
        }
        else
        {
            switch (statusCode)
            {
                // 处理 401 状态码
                case StatusCodes.Status401Unauthorized:
                    await context.Response.WriteAsJsonAsync(BaseResponse<object>.Failed("验证失败，请重新登录！"),
                        App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
                    break;
                // 处理 403 状态码
                case StatusCodes.Status403Forbidden:
                    await context.Response.WriteAsJsonAsync(BaseResponse<object>.Failed("没有权限！"),
                        App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
                    break;
                // 处理 404 状态码
                case StatusCodes.Status404NotFound:
                    context.Response.StatusCode = 404;
                    await context.Response.WriteAsJsonAsync(BaseResponse<object>.Failed("资源不存在！"),
                        App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
                    break;
            }
        }
    }
}